package raft

import (
	"errors"
	"strconv"
	"strings"
	"time"
)

// peers nodeId:peer
type peers map[uint64]*peer

type peer struct {
	id               uint64            // 节点id
	endpoint         Endpoint          // 节点地址
	stopFlag         bool              // 节点是否已经停机
	stopAt           int64             // 节点停机时间戳
	replicatingState *replicatingState // 复制状态
}

func (p *peer) String() string {
	return string(p.endpoint)
}

// stop 设置节点已经停机
func (p *peer) stop() {
	p.stopFlag = true
	p.stopAt = time.Now().UnixMilli()
}

func (p peers) add(id uint64, endpoint Endpoint) {
	p[id] = &peer{id: id, endpoint: endpoint}
}

// quorumSize 需要的投票数
func (p peers) quorumSize() int {
	return len(p)/2 + 1
}

func newPeers(cluster []string) (peers, error) {
	ps := peers{}

	for _, c := range cluster {
		tmp := strings.Split(c, "@")

		if len(tmp) != 2 {
			return nil, errors.New("invalid cluster format")
		}

		id, err := strconv.ParseUint(tmp[0], 10, 64)
		if err != nil {
			return nil, err
		}

		e := Endpoint(tmp[1])

		ps[id] = &peer{
			id:       id,
			endpoint: e,
		}
	}

	return ps, nil
}

// replicatingState 日志复制状态
type replicatingState struct {
	nextIndex        uint64 // 下一条日志索引
	matchIndex       uint64 // 匹配索引
	replicating      bool   // 是否正在复制
	lastReplicatedAt int64  // 最后一次日志复制时间戳毫秒
}

func newReplicatingState(nextIndex uint64) *replicatingState {
	return &replicatingState{
		nextIndex:        nextIndex,
		matchIndex:       0,
		replicating:      false,
		lastReplicatedAt: -1,
	}
}
